
var common = require("./common") 
var db = require("./db");
var kurento = require('kurento-client');
const kms = require("./kms");

class TTask{
    constructor(){
        this.objType ="";
        this.clientId ="";
        this.code ="";
        this.parentCode ="";
        this.clientId ="";
        this.url ="";
        this.srcCode ="";
    }
}

class TBuf{
    constructor(){
        this.codeBuf ={};
        this.idBuf={};
        this.dbKey ="";
        this.db =new db.TDBMySql();
        this.client = null;
    } 
    loadFromDB( client  ){
        return new Promise((success , faild)=>{
            var me = this;
            try{ 
                me.client = client;
                var codeBuf = {} ;
                var idBuf = {};
                var sql ="select * from T_KmsObj";
                var freeItems =[];
                me.db.query( me.dbKey , sql , {} , function(res){
                    var items = res.result;
                    var loadItem = function(){
                        if( items.length>0){
                            var item = items.shift();
                            client.getMediaobjectById(item.kmsId, function(erFind , obj){
                                if( common.TComm.isnull(obj) ){
                                    freeItems.push(item.kmsId);
                                }
                                else{
                                    obj.info = item;
                                    codeBuf[item.code] = obj;
                                    idBuf[item.kmsId] = obj;
                                }
                                loadItem();
                            });
                        }
                        else{
                            me.codeBuf = codeBuf;
                            me.idBuf = idBuf;
                            if( freeItems.length>0){
                                sql = "delete from T_KmsObj where kmsId in ('0'";
                                for( var i=0;i<freeItems.length;i++){
                                    sql += ",'"+ freeItems[i]+"'";
                                }
                                sql +=")";
                                me.db.query(me.dbKey , sql , {} ,function(resDelete){
                                    success();
                                });
                            }
                            else{
                                success();
                            }
                        }
                    }
                    loadItem();
                })
            }
            catch(er){
                console.log(er);
                success();
            }
        })
    }
    setItem( obj , code , clientId  ){
        return new Promise((success , faild)=>{
            var me = this;
            try{ 
                if(common.TComm.isnull(obj)){
                    success(null);
                }
                else{
                    var ps={
                        code:code ,
                        clientId:clientId ,
                        kmsId: obj.id
                    };
                    var sql = "delete from T_KmsObj where kmsId=:kmsId;insert into T_KmsObj(code , kmsId , clientId)values(:code , :kmsId , :clientId);";
                    me.db.query(me.dbKey , sql , ps , function(res){
                        var flag = res.result && res.result.length>1 && res.result[1].insertId>0;
                        if( flag ){
                            ps.F_ID = res.result[1].insertId;
                            obj.info = ps;
                            me.codeBuf[ps.code] = obj;
                            me.idBuf[ps.kmsId] = obj;
                            success(obj);
                        }
                        else{
                            success(null);
                        }
                    })
                }
            }
            catch(er){
                console.log(er);
                success();
            }
        })
    }
    getItemByCode( code   ){
        var me = this;
        return me.codeBuf[code]?me.codeBuf[code]: null;
    }
    getItemByKmsId( kmsId   ){
        var me = this;
        return me.idBuf[kmsId]?me.idBuf[kmsId]: null;
    } 
} 

class THhKms{
    constructor(){
        this.config={
            dbKey:'telemedicine',
            dbInfo:{
                host:"tjiot.hhdata.cn" ,
                port:53306,
                uid:"root",
                pwd:"hhuc1115",
                db:"telemedicine" ,
                sqlPath:""
            },
            kmsUrl:"wss://ssl.hhdata.cn:40014/kurento" ,
            appPipeName :"hhAppPipe"
        };
        this.buf = new TBuf();   
        this.db = new db.TDBMySql();     
        this.kmsClient = null; 
    }
    init(){
        var me = this;
        me.db.apps[me.config.dbKey] = me.config.dbInfo;
        me.buf.dbKey = me.config.dbKey;
        me.buf.db = me.db;
    }
    getClient(){
        return new Promise((success , faild)=>{
            var me = this;
            try{
                if( common.TComm.isnull(me.kmsClient)){
                    kurento( me.config.kmsUrl).then(client=>{
                        me.kmsClient = client;
                        me.buf.loadFromDB( client ).then(()=>{
                            success();
                        });
                    })
                }
                else{
                    success(me.kmsClient);
                }
            }
            catch(er){
                console.log(er);
                success();
            }
        })
    } 
    createKmsObj( task ){ 
        return new Promise((success , faild)=>{
            var me = this;
            try{
                me.getClient().then(client=>{
                    me.buf.client = client;
                    var parent = me.buf.getItemByCode(task.parentCode);
                    var srcObj = me.buf.getItemByCode(task.srcCode);
                    var onCreate=function(obj){
                        me.buf.setItem( obj , task.code , task.clientId).then( newObj =>{
                            success(newObj);
                        })
                    }
                    if( task.objType=="MediaPipeline"){
                        client.create(task.objType).then(obj=>{
                            onCreate(obj);
                        })
                    }
                    else if( 
                        task.objType=="WebRtcEndpoint" || task.objType=="RtpEndpoint" || 
                        task.objType=="Composite" || task.objType=="Dispatcher" 
                    ){
                        parent.create(task.objType).then(obj=>{
                            onCreate(obj);
                        })
                    }
                    else if(  task.objType=="PlayerEndpoint" ){
                        parent.create(task.objType , {uri: task.url}).then(obj=>{
                            obj.on("EndOfStream" , function(){
                                obj.play();
                            })
                            obj.play(function(){
                                onCreate(obj);
                            })
                        })
                    }
                    else if(  task.objType=="HubPort" ){
                        parent.createHubPort().then(obj=>{
                            onCreate(obj);
                            /*
                            if( srcObj!=null ){
                                var arr= srcObj.id.split(".");
                                var isHubPort =  arr[arr.length-1]=="HubPort";
                                if( isHubPort){
                                    parent.connect(srcObj , obj , function(erConn){
                                        onCreate(obj);
                                    })
                                }
                                else{
                                    srcObj.connect(obj , function(erConn){
                                        onCreate(obj);
                                    })
                                }
                            }
                            else{
                                onCreate(obj);
                            }
                            */
                        })
                    }
                })
            }
            catch(er){
                console.log(er);
                success();
            }
        })
    }
    loadKmsObj( task ){
        return new Promise((success , faild)=>{
            var me = this; 
            try{
                me.getClient().then(client=>{
                    me.buf.client = client;
                    var obj = me.buf.getItemByCode(task.code);
                    var onLoadObj = function(obj){
                        if( task.srcCode.length>0){
                            var parent = me.buf.getItemByCode(task.parentCode);
                            var srcObj = me.buf.getItemByCode(task.srcCode);
                            if ( srcObj && srcObj!=null){
                                if( srcObj.id.indexOf(".HubPort")>0){
                                    parent.connect(srcObj , obj , function(erConn){
                                        success(obj);
                                    })
                                }
                                else{
                                    srcObj.connect(obj, "VIDEO").then(()=>{
                                        success(obj);
                                    })
                                }
                            }
                            else{
                                success(obj);
                            }
                        }
                        else{
                            success(obj);
                        }
                    }
                    if( common.TComm.isnull(obj)){
                        me.createKmsObj(task).then(newObj=>{
                            //onLoadObj(newObj)
                            success(newObj);
                        })
                    }
                    else{
                        success(obj);
                    }
                })
            }
            catch(er){
                console.log(er);
                success();
            }
        })
    }
    loadKmsObjs( taskItems ){
        return new Promise((success , faild)=>{
            var me = this; 
            try{
                var res = {};
                var items = JSON.parse(JSON.stringify(taskItems));
                var loadItem= function(){
                    if( items.length>0){
                        var task = items.shift();
                        me.loadKmsObj(task).then(obj=>{
                            res[obj.info.code] = obj;
                            loadItem();
                        })
                    }
                    else{
                        success(res);
                    }
                }
                loadItem();

            }
            catch(er){
                console.log(er);
                success();
            }
        })
    }
    connectHubPortById( srcId , targetId ){
        return new Promise((success , faild)=>{
            var me = this;
            try{
                var arr = srcId.split("/");
                var hubId = arr[0]+"/"+arr[1];
                var hub = me.buf.getItemByKmsId(hubId);
                var src = me.buf.getItemByKmsId(srcId);
                var target = me.buf.getItemByKmsId(targetId);
                var res={
                    state :0
                };
                if( common.TComm.isnull(hub)){
                    res.state = -3;
                }
                else if( common.TComm.isnull(target)){
                    res.state = -2;
                }
                else if( common.TComm.isnull(src)){
                    res.state = -1;
                }
                if( res.state<0){
                    success(res);
                }
                else{
                    hub.connect(src , target , function(erConn){
                        if( common.TComm.isnull(erConn)){
                            res.state = 1;
                        }
                        success(res);
                    })
                }

            }
            catch(er){
                console.log(er);
                success();
            }
        })
    }
    setObjInfo( kmsId , code , clientId ){
        return new Promise((success , faild)=>{
            var me = this;
            try{
                me.getClient().then( client=>{
                    client.getMediaobjectById( kmsId , function(erObj, obj){
                        if( common.TComm.isnull(obj) ){
                            success(null);
                        }
                        else{
                            me.buf.setItem(obj , code , clientId ).then(newObj=>{
                                success(newObj);
                            })
                        }
                    })
                })
            }
            catch(er){
                console.log(er);
                success();
            }
        })
    }
    connectObjs( connectTasks ){
        return new Promise((success , faild)=>{
            var me = this;
            try{
                var tasks = JSON.parse(JSON.stringify(connectTasks));
                var loadItem = function(){
                    if( tasks.length>>0){
                        var task = tasks.shift();
                        var src = me.buf.getItemByKmsId(task.srcId);
                        var tar = me.buf.getItemByKmsId(task.targetId);
                        var state = 0;
                        if( common.TComm.isnull(src)){
                            state = -1; 
                        }
                        else if( common.TComm.isnull(tar)){
                            state = -2; 
                        }

                        if( state<0){
                            task.state = state;
                            loadItem();
                        }
                        else{
                            var flag =  task.mt && task.mt!=null && (task.mt=="VIDEO" || task.mt=="AUDIO") ;
                            if( src.id.indexOf(".HubPort")>0 &&  tar.id.indexOf(".HubPort")>0 ){
                                var arr = src.id.split("/");
                                var hubId = [arr[0], arr[1]].join("/");
                                var hub = me.buf.getItemByKmsId(hubId);
                                if( common.TComm.isnull(hub) ){
                                    task.state = -3;
                                    loadItem();
                                }
                                else{
                                    hub.connect(src , tar).then(()=>{
                                        task.state = 1;
                                        loadItem();
                                    })
                                }
                            }
                            else{
                                if( flag){
                                    src.connect(tar , task.mt).then(()=>{
                                        task.state = 1;
                                        loadItem();
                                    })
                                }
                                else{
                                    src.connect(tar).then(()=>{
                                        task.state = 1;
                                        loadItem();
                                    })
                                }
                            }
                        }
                    }
                    else{
                        success(connectTasks);
                    }
                }
                loadItem();
            }
            catch(er){
                console.log(er);
                success();
            }
        })
    }


    
    regist2WebSvr(webSvr){
        var me = this;
        if( webSvr && webSvr!=null){
            var respJson = function(result , response){
                try{
                    response.send(JSON.stringify(result));
                }
                catch(eer){
                    console.log(eer);
                }
            }
            webSvr.registRoute ( "common" , "hhwms" , "setObjInfo" , function( result , request , response ){                
                try{
                    var kmsId = result.ps.kmsId ; 
                    var code = result.ps.code ; 
                    var clientId = result.ps.clientId ; 
                    me.setObjInfo( kmsId , code , clientId).then(obj=>{
                        var res = common.TComm.isnull(obj)?null : obj.info;
                        result.data = res;
                        respJson(result, response);
                    });
                }
                catch(err){
                    console.log(err);
                    respJson(result, response);
                }
            }); 
            webSvr.registRoute ( "common" , "hhwms" , "connectHubPortById" , function( result , request , response ){                
                try{
                    var srcId = result.ps.srcId ; 
                    var targetId = result.ps.targetId ; 
                    me.connectHubPortById(  srcId , targetId ).then(res=>{
                        result.data = res;
                        respJson(result, response);
                    });
                }
                catch(err){
                    console.log(err);
                    respJson(result, response);
                }
            }); 
            webSvr.registRoute ( "common" , "hhwms" , "loadKmsObjs" , function( result , request , response ){                
                try{
                    var taskJson = result.ps.TaskJson ; 
                    var taskItems = JSON.parse(taskJson);
                    me.loadKmsObjs( taskItems).then(res=>{                        
                        var objs = Object.values(res);
                        var infos = {};
                        objs.forEach(function(obj){
                            infos[obj.info.code] = obj.info;
                        })
                        result.data = infos;
                        respJson(result, response);
                    });
                }
                catch(err){
                    console.log(err);
                    respJson(result, response);
                }
            }); 
            webSvr.registRoute ( "common" , "hhwms" , "connectObjs" , function( result , request , response ){                
                try{
                    var taskJson = result.ps.TaskJson ; 
                    var taskItems = JSON.parse(taskJson);
                    me.connectObjs( taskItems).then(res=>{        
                        result.data = res;
                        respJson(result, response);
                    });
                }
                catch(err){
                    console.log(err);
                    respJson(result, response);
                }
            }); 
        }
    }
}


module.exports ={
    TTask : TTask ,
    TBuf : TBuf , 
    THhKms: THhKms
}




